package edu.towson.cosc603.coffeemaker;

import org.junit.Test;

import junit.framework.TestCase;

/**
 *
 */
public class CoffeeMakerTest extends TestCase {
	private CoffeeMaker cm;
	private Inventory i;
	private Recipe r1;

	public void setUp() {
		cm = new CoffeeMaker();
		i = cm.checkInventory();

		r1 = new Recipe();
		r1.setName("Coffee");
		r1.setPrice(50);
		r1.setAmtCoffee(6);
		r1.setAmtMilk(1);
		r1.setAmtSugar(1);
		r1.setAmtChocolate(0);
	}

	@Test
	public void testAddRecipe1() {
		assertTrue(cm.addRecipe(r1));
	}
	
	/**
	 * Test for adding the same recipe
	 */
	@Test
	public void testAddRecipe2() {
		cm.addRecipe(r1);
		assertFalse(cm.addRecipe(r1));
	}
	
	/**
	 * Test for adding too many recipes
	 */
	@Test
	public void testAddRecipe3() {
		Recipe r2 = new Recipe(), r3 = new Recipe(), r4 = new Recipe(), r5 = new Recipe();
		r2.setName("Coffee2");
		r2.setPrice(1);
		r3.setName("Coffee3");
		r3.setPrice(1);
		r4.setName("Coffee4");
		r4.setPrice(1);
		r5.setName("Coffee5");
		r5.setPrice(1);
		cm.addRecipe(r1);
		cm.addRecipe(r2);
		cm.addRecipe(r3);
		cm.addRecipe(r4);
		assertFalse(cm.addRecipe(r5));
	}
	
	@Test
	public void testDeleteRecipe1() {
		cm.addRecipe(r1);
		assertTrue(cm.deleteRecipe(r1));
	}
	
	/*
	 * Test deleting a null recipe
	 */
	@Test
	public void testDeleteRecipe2() {
		r1 = null;
		assertFalse(cm.deleteRecipe(r1));
	}
	
	/*
	 * Test deleting the same recipe
	 */
	@Test
	public void testDeleteRecipe3() {
		cm.deleteRecipe(r1);
		assertFalse(cm.deleteRecipe(r1));
	}

	@Test
	public void testEditRecipe1() {
		cm.addRecipe(r1);
		Recipe newRecipe = new Recipe();
		newRecipe = r1;
		newRecipe.setAmtSugar(2);
		assertTrue(cm.editRecipe(r1, newRecipe));
	}
		
	/*
	 * Test editing a recipe different name
	 */
	@Test
	public void testEditRecipe3() {
		Recipe r2 = new Recipe(), r3 = new Recipe(), r4 = new Recipe(), r5 = new Recipe();
		r2.setName("Coffee2");
		r2.setPrice(1);
		r3.setName("Coffee3");
		r3.setPrice(1);
		r4.setName("Coffee4");
		r4.setPrice(1);
		r5.setName("Coffee5");
		r5.setPrice(1);
		cm.addRecipe(r1);
		cm.addRecipe(r2);
		cm.addRecipe(r3);
		cm.addRecipe(r4);
		
		Recipe newRecipe = new Recipe();
		newRecipe = r1;
		newRecipe.setName("Coffee2");
		assertFalse(cm.editRecipe(r1, newRecipe));
	}	
	
	@Test
	public void testAddInventory1() {
		assertTrue(cm.addInventory(1, 1, 1, 1));
	}
	
	/**
	 * Test adding inventory with negative values
	 */
	@Test
	public void testAddInventory2() {
		assertFalse(cm.addInventory(-1, 1, 1, 1));
	}

	/**
	 * Test adding inventory with negative values
	 */
	@Test
	public void testAddInventory3() {
		assertFalse(cm.addInventory(1, -1, 1, 1));
	}

	/**
	 * Test adding inventory with negative values
	 */
	@Test
	public void testAddInventory4() {
		assertFalse(cm.addInventory(1, 1, -1, 1));
	}

	/**
	 * Test adding inventory with negative values
	 */
	@Test
	public void testAddInventory5() {
		assertFalse(cm.addInventory(1, 1, 1, -1));
	}

	/**
	 * Test adding inventory with negative values
	 */
	@Test
	public void testAddInventory6() {
		assertFalse(cm.addInventory(-1, 1, 1, -1));
	}

	/**
	 * Test adding inventory with negative values
	 */
	@Test
	public void testAddInventory7() {
		assertFalse(cm.addInventory(1, -1, 1, -1));
	}

	/**
	 * Test adding inventory with negative values
	 */
	@Test
	public void testAddInventory8() {
		assertFalse(cm.addInventory(1, 1, -1, -1));
	}

	/**
	 * Test adding inventory with negative values
	 */
	@Test
	public void testAddInventory9() {
		assertFalse(cm.addInventory(-1, -1, 1, 1));
	}

	/**
	 * Test adding inventory with negative values
	 */
	@Test
	public void testAddInventory10() {
		assertFalse(cm.addInventory(-1, 1, -1, 1));
	}

	/**
	 * Test adding inventory with negative values
	 */
	@Test
	public void testAddInventory11() {
		cm.addInventory(1, 0, 0, 0);
		assertEquals(16, i.getCoffee(), 0);
	}
	
	/**
	 * Test adding inventory with negative values
	 */
	@Test
	public void testAddInventory12() {
		cm.addInventory(0, 1, 0, 0);
		assertEquals(16, i.getMilk(), 0);
	}
	
	/**
	 * Test adding inventory with negative values
	 */
	@Test
	public void testAddInventory13() {
		cm.addInventory(0, 0, 1, 0);
		assertEquals(16, i.getSugar(), 0);
	}
	
	/**
	 * Test adding inventory with negative values
	 */
	@Test
	public void testAddInventory14() {
		cm.addInventory(0, 0, 0, 1);
		assertEquals(16, i.getChocolate(), 0);
	}
	
	@Test
	public void testCheckInventory() {
		assertEquals(i.toString(), cm.checkInventory().toString());
	}
	
	/**
	 * Returns correct change
	 */
	@Test
	public void testPurchaseBeverage1() {
		assertEquals(10, cm.makeCoffee(r1, 60), 0);
	}
	
	/**
	 * Returns false, not enough money
	 */
	@Test
	public void testPurchaseBeverage2() {
		assertEquals(40, cm.makeCoffee(r1, 40), 0);
	}
	
	/**
	 * Returns false, not enough ingredients
	 */
	@Test
	public void testPurchaseBeverage3() {
		Recipe editRecipe = r1;
		editRecipe.setAmtChocolate(100);
		cm.editRecipe(r1, editRecipe);
		cm.getRecipeForName("Coffee");
		assertEquals(40, cm.makeCoffee(r1, 40), 0);
	}
	
	@Test
	public void testGetRecipes() {
		cm.addRecipe(r1);
		cm.getRecipes();
	}
	
	@Test
	public void testGetRecipeForName1() {
        cm.addRecipe(r1);
        assertEquals(r1,cm.getRecipeForName("Coffee"));
	}
	
	@Test (expected=Exception.class)
	public void testGetRecipeForName2() {
        cm.addRecipe(r1);
        assertNull(cm.getRecipeForName("Coffee2").getName());
	}
	
	@Test
	public void testMakeCoffee1() {
		assertEquals(0, cm.makeCoffee(r1, 50), 0);
	}
}